#include "HL2Interface.h"

HL2Interfaces g_pInterfaces;

/////////////////////////////////////////////////////
// Hooks

CUserCmd* __stdcall hkGetUserCmd(int seq)
{
	DWORD GetUserCmd = *(DWORD*)((DWORD)g_pInterfaces.g_pInput + 0xC4) + (seq  % 90 << 6);
	CUserCmd* pCmd = (CUserCmd*)GetUserCmd;
	JUNK_CODE;
	CUserCmd Temp;
	Temp = *pCmd;
	JUNK_CODE;

	g_pNoSpread.ApplySeedSpread(pCmd);
	JUNK_CODE;

	g_pBHop.Compute(pCmd);

	return pCmd;
}

void __fastcall hkCreateMove(void* thisptr, int edx, int sequence_number, float input_sample_frametime, bool active) 
{
	typedef void (__thiscall *CreateMove_t) (void*, int sequence_number, float input_sample_frametime, bool active);
	g_pInterfaces.g_pClientHooks->GetMethod<CreateMove_t>(CLIENT_CREATEMOVE)(thisptr, sequence_number, input_sample_frametime, active);

	if(!g_pInterfaces.g_pInput)
		return;

	JUNK_CODE;
	CVerifiedUserCmd* pSafeCommand = *(CVerifiedUserCmd**)((size_t)g_pInterfaces.g_pInput + 0xC8) + (sequence_number % 90);
	CUserCmd* pCmd = g_pInterfaces.g_pInput->GetUserCmd(sequence_number); 

	if(!pCmd)
		return;

	g_pNoHands.Compute();
	g_pNoflash.Compute();
	JUNK_CODE;
	g_pNoSmoke.Compute();
	g_pCheats.Compute();
	g_pHudRadar.Compute();
	/*g_pSpeedhack2.Set((GetAsyncKeyState('F') & (1<<15)) != 0);*/
	JUNK_CODE;
	g_pNoSpread.ApplyNoRecoil(pCmd, g_pAimbot.Compute(pCmd));
	g_pEasyTrigger.Compute(pCmd);
	JUNK_CODE;
	g_pAutoPistol.Compute(pCmd);
	g_pKnifebot.Compute(pCmd);

	//if(pCmd->buttons & IN_ATTACK)
	//{
	//	g_pSpeedhack2.Disable();
	//}

	//g_pSpeedhack2.Compute();

	JUNK_CODE;
	GameUtilities::FixAngle(&pCmd->viewangles);

	g_pEventManager.RegisterSelf();

	pSafeCommand->m_cmd = *pCmd;
	JUNK_CODE;
	pSafeCommand->m_crc = pSafeCommand->m_cmd.GetChecksum();
}

void __fastcall hkPaintTraverse(void* thisptr, int edx, unsigned int vguiPanel, bool forceRepaint, bool allowForce)
{
	typedef const char* (__thiscall* GetName_t)(void*, unsigned int);
	const char* name = g_pInterfaces.g_pPanelHooks->GetMethod<GetName_t>(PANEL_GETNAME)(thisptr, vguiPanel);
	JUNK_CODE;

	typedef void (__thiscall *PaintTraverse_t)(void* thisptr, unsigned int vguiPanel, bool forceRepaint, bool allowForce);
	g_pInterfaces.g_pPanelHooks->GetMethod<PaintTraverse_t>(PANEL_PAINTTRAVERSE)(thisptr, vguiPanel, forceRepaint, allowForce);

	if(name[0] == 'M' && name[3] == 'S' && name[9] == 'T' && name[12] == 'P') // [M]at[S]ystem[T]op[P]anel
	{
		JUNK_CODE;
		// Draw Here
		g_pESP.Init();

		if(!g_pInterfaces.g_pEngine->IsInGame())
			return;

		g_pFont->PrintString(15, 15, 255, 255, 255, 255, FA_Left|FA_CenterH, /*Tettenhook 1.0.6*/XorStr(16, 0x48, 0x1CA232B1, 0x21AD2AAE, 0x2FD41E8C, 0x128B148F).c_str());

		char TokenStr[1024];
		strcpy(TokenStr, g_pConfigManager.GetActiveFeatureString());
		JUNK_CODE;
		char* Token = TokenStr;
		int YOffset = 260;
		Token = strtok(TokenStr, "\n");
		JUNK_CODE;
		while (Token)
		{
			g_pFont->PrintString(15, YOffset, 255, 0, 0, 255, FA_Left|FA_CenterH, "%s", Token);
			YOffset += 20;
			Token = strtok(NULL, "\n");
		}
		//g_pFont->PrintString(15, 100, 255, 0, 0, 255, FA_Left|FA_CenterH, "%s", g_pConfigManager.GetActiveFeatureString());

		JUNK_CODE;
		g_pESP.Draw();

		g_pCrosshair.Draw();
	}
}

IMaterial* __fastcall hkFindMaterial(void* thisptr, int edx, char const* pMaterialName, const char *pTextureGroupName, bool complain/* = true*/, const char *pComplainPrefix/* = NULL*/)
{
	typedef IMaterial* (__thiscall* FindMaterial_t)(void*, char const*, const char *, bool complain, const char *);
	IMaterial* ret = g_pInterfaces.g_pMaterialHooks->GetMethod<FindMaterial_t>(MATSYS_FINDMATERIAL)(thisptr, pMaterialName, pTextureGroupName, complain, pComplainPrefix);
	g_pCheats.ComputeAsus(ret);
	return ret;
}

/////////////////////////////////////////////////////
// Base Funcs

void HL2Interfaces::Start()
{
	if(WaitForGame())
	{
		LoadInterfaces();
		NetvarManager::PullOffsets();
	}
}

bool HL2Interfaces::WaitForGame()
{
	HANDLE hClient = NULL, hEngine = NULL, hVGUI = NULL, hVGUI2 = NULL, hMatSys = NULL;
	while(!hClient || !hEngine || !hVGUI || !hVGUI2)
	{
		hClient = GetModuleHandleA(/*client.dll*/XorStr(10, 0xEE, 0x8D01850E, 0x841DC603, 0x8A090000).c_str());
		hEngine = GetModuleHandleA(/*engine.dll*/XorStr(10, 0x86, 0xE36BE36A, 0xEC64AE9B, 0x12910000).c_str());
		JUNK_CODE;
		hVGUI   = GetModuleHandleA(/*vguimatsurface.dll*/XorStr(18, 0x41, 0x37A74AD7, 0x50DD4FC9, 0x4CCA51D7, 0x56D11DD6, 0x5DDC0000).c_str());
		hVGUI2	= GetModuleHandleA(/*vgui2.dll*/XorStr(9, 0x7F, 0x09990895, 0x49D41D94, 0x1B000000).c_str());
		JUNK_CODE;
		hMatSys = GetModuleHandleA(/*materialsystem.dll*/XorStr(18, 0x9A, 0xF778EC72, 0xE47CF57F, 0xE168E37B, 0xEB60A26F, 0xE6650000).c_str());
	}
	return true;
}

void HL2Interfaces::LoadInterfaces()
{
	//////////////////////////////////////////////////////////////////////////

	/*AllocConsole();
	freopen("CONOUT$", "w", stdout);
	freopen("CONOUT$", "w", stderr);
	freopen("CONIN$", "r", stdin);
	SetConsoleTitle(L"OSH-Base Debug");
	system("color 05");
	HANDLE ConsoleHandle = GetStdHandle(STD_OUTPUT_HANDLE);
	_CONSOLE_SCREEN_BUFFER_INFO info;
	system("mode CON: COLS=200");
	GetConsoleScreenBufferInfo(ConsoleHandle,&info);
	SMALL_RECT windowMaxSize = {0, 0, info.dwMaximumWindowSize.X-1, info.dwMaximumWindowSize.Y-1};
	SetConsoleWindowInfo(ConsoleHandle, TRUE, &windowMaxSize);*/
	
	//////////////////////////////////////////////////////////////////////////


	CreateInterfaceFn fnClient = NULL;
	CreateInterfaceFn fnEngine = NULL;
	CreateInterfaceFn fnVGUI   = NULL;
	JUNK_CODE;
	CreateInterfaceFn fnVGUI2  = NULL;
	JUNK_CODE;
	CreateInterfaceFn fnMatSys = NULL;


	fnClient = (CreateInterfaceFn)(GetProcAddress(GetModuleHandleA(/*client.dll*/XorStr(10, 0xEE, 0x8D01850E, 0x841DC603, 0x8A090000).c_str()), /*CreateInterface*/XorStr(15, 0x95, 0xD666F673, 0xE575C660, 0xF969F96C, 0xE86BE200).c_str()));
	fnEngine = (CreateInterfaceFn)(GetProcAddress(GetModuleHandleA(/*engine.dll*/XorStr(10, 0x86, 0xE36BE36A, 0xEC64AE9B, 0x12910000).c_str()),	/*CreateInterface*/XorStr(15, 0x95, 0xD666F673, 0xE575C660, 0xF969F96C, 0xE86BE200).c_str()));
	JUNK_CODE;
	fnVGUI	 = (CreateInterfaceFn)(GetProcAddress(GetModuleHandleA(/*vguimatsurface.dll*/XorStr(18, 0x41, 0x37A74AD7, 0x50DD4FC9, 0x4CCA51D7, 0x56D11DD6, 0x5DDC0000).c_str()), /*CreateInterface*/XorStr(15, 0x95, 0xD666F673, 0xE575C660, 0xF969F96C, 0xE86BE200).c_str()));
	fnVGUI2	 = (CreateInterfaceFn)(GetProcAddress(GetModuleHandleA(/*vgui2.dll*/XorStr(9, 0x7F, 0x09990895, 0x49D41D94, 0x1B000000).c_str()), /*CreateInterface*/XorStr(15, 0x95, 0xD666F673, 0xE575C660, 0xF969F96C, 0xE86BE200).c_str()));
	JUNK_CODE;
	fnMatSys = (CreateInterfaceFn)(GetProcAddress(GetModuleHandleA(/*materialsystem.dll*/XorStr(18, 0x9A, 0xF778EC72, 0xE47CF57F, 0xE168E37B, 0xEB60A26F, 0xE6650000).c_str()), /*CreateInterface*/XorStr(15, 0x95, 0xD666F673, 0xE575C660, 0xF969F96C, 0xE86BE200).c_str()));

	g_pClient			= (IBaseClientDLL*)fnClient(/*VClient017*/XorStr(10, 0x14, 0x42D07EF8, 0x75E17ABD, 0x3DBC0000).c_str(), NULL);
	g_pEntList			= (IClientEntityList*)fnClient(/*VClientEntityList003*/XorStr(20, 0xF5, 0xA3379F1B, 0x941E9B2B, 0x8318821E, 0x90248E15, 0x9154D351).c_str(), NULL);
	JUNK_CODE;
	g_pEngine			= (IVEngineClient*)fnEngine(/*VEngineClient014*/XorStr(16, 0xBB, 0xED7FD75F, 0xDE58D077, 0xDF5BD45E, 0xDB1E9C18).c_str(), NULL);
	g_pEngineTrace      = (IEngineTrace*)fnEngine(/*EngineTraceClient003*/XorStr(20, 0x27, 0x62C842CD, 0x4DC775D2, 0x7EFD78DF, 0x77F37CF6, 0x63A625A7).c_str(), NULL);
	JUNK_CODE;
	g_pMaterialSystem   = (IMaterialSystem*)fnMatSys(/*VMaterialSystem080*/XorStr(18, 0xC5, 0x9309A236, 0xA432D65F, 0xD16FC249, 0xCD5DDA06, 0x8D040000).c_str(), NULL);
	g_pGameEventManager = (IGameEventManager2*)fnEngine(/*GAMEEVENTSMANAGER002*/XorStr(20, 0x59, 0x1E991A93, 0x1082169C, 0x0583028F, 0x038D0C8F, 0x1BF877F4).c_str(), NULL);

	void* vPanel	= fnVGUI2(/*VGUI_Panel009*/XorStr(13, 0x4A, 0x1C8E1D8E, 0x199525AD, 0x27AD708F, 0x07000000).c_str(), NULL);
	JUNK_CODE;
	void* vReplay	= fnEngine(/*EngineClientReplay001*/XorStr(21, 0xE8, 0xAD09810C, 0x8A06A10D, 0x893AB029, 0x8E3EAA35, 0xB92EE665, 0xE5000000).c_str(), NULL);

	DWORD dwClient = (DWORD)GetModuleHandleA(/*client.dll*/XorStr(10, 0xEE, 0x8D01850E, 0x841DC603, 0x8A090000).c_str());
	JUNK_CODE;
	BYTE InputFindPatternA[] = {0xB9, 0x00, 0x00, 0x00, 0x00, 0xE8, 0x00, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0xC7, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE8, 0x00, 0x00, 0x00, 0x00, 0x59, 0xC3, 0x68, 0x00, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0xB9, 0x00, 0x00, 0x00, 0x00};
	g_pInput		= (CInput*)*(DWORD*)(FindPattern::Find(dwClient, 0x89B000 - 0x100, InputFindPatternA, XorStr(InputFindPatternB).c_str()) + InputPatternOffset);
	JUNK_CODE;

	BYTE VelocityOffsetFindPatternA[] = {0x55, 0x8B, 0xEC, 0x83, 0xEC, 0x0C, 0x56, 0x8B, 0xF1, 0xE8, 0x00, 0x00, 0x00, 0x00, 0x3B, 0xF0};
	Offsets::EstimateAbsVelocity = FindPattern::Find(dwClient, 0x89B000 - 0x100, (BYTE*) VelocityOffsetFindPatternA, XorStr(VelocityOffsetFindPatternB).c_str()) + VelocityOffsetFindPatternOffset;

	g_pKnifebot.Init();
	g_pNoHands.Init();
	g_pNoSmoke.Init();
	g_pNoflash.Init();
	/*g_pSpeedhack2.Init();*/
	g_pCrosshair.Init();
	JUNK_CODE;
	g_pAimbot.Init();
	g_pNoSpread.Init();
	g_pEasyTrigger.Init();
	g_pCheats.Init();
	g_pBHop.Init();
	JUNK_CODE;
	g_pAutoPistol.Init();
	g_pHudRadar.Init();
	g_pEventManager.Init();
	
	g_pConfigManager.Load();

	g_pSurface.Init((PDWORD_PTR*)fnVGUI(/*VGUI_Surface030*/XorStr(15, 0xE2, 0xB426B516, 0x810EA929, 0xBC38BB32, 0xE666E400).c_str(), NULL));
	JUNK_CODE;
	g_pFont = Font::BuildFont(/*Helvetica*/XorStr(9, 0xF0, 0xB80A821B, 0x891F830A, 0x89000000).c_str(), 14, 350, FF_OUTLINE|FF_DROPSHADOW);

	if(g_pInput)
	{
		static hook_t InputHook((void*)g_pInput);
		g_pInputHooks = &InputHook;
		JUNK_CODE;
		InputHook.HookMethod(&hkGetUserCmd, INPUT_GETUSERCMD);
	}

	if(g_pClient)
	{
		static hook_t ClientHook((void*)g_pClient);
		JUNK_CODE;
		g_pClientHooks = &ClientHook;
		ClientHook.HookMethod(&hkCreateMove, CLIENT_CREATEMOVE);
	}

	if(vPanel)
	{
		static hook_t PanelHook(vPanel);
		JUNK_CODE;
		g_pPanelHooks = &PanelHook;
		PanelHook.HookMethod(&hkPaintTraverse, PANEL_PAINTTRAVERSE);
	}

	if(g_pMaterialSystem)
	{
		static hook_t MHook(g_pMaterialSystem);
		g_pMaterialHooks = &MHook;
		JUNK_CODE;
		MHook.HookMethod(&hkFindMaterial, MATSYS_FINDMATERIAL);
	}

	if(vReplay)
	{
		hook_t ReplayHook(vReplay);
		typedef CGlobalVarsBase* (__thiscall* GetGlobalVars_t)(void*);
		JUNK_CODE;
		g_pGlobals = ReplayHook.GetMethod<GetGlobalVars_t>(REPLAY_GETGLOBALVARS)(vReplay);
	}
}